package com.alongthink.javademo.socketio;

import com.alongthink.javademo.globalClass.ResultBody;
import com.alongthink.javademo.globalClass.SocketIOResultBody;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIONamespace;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.DataListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Slf4j
@Service
public class MySocket {
    public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>();

    public void start(int port){
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setHostname("0.0.0.0");
        config.setPort(port);

        SocketIOServer server = new SocketIOServer(config);

        //添加命名空间，连接地址：http://ip:port/msg
        SocketIONamespace msg_namespace = server.addNamespace("/msg");

        //添加监听浏览器发送消息事件
        msg_namespace.addEventListener("message", ResultBody.class, new DataListener<ResultBody>() {
            @Override
            public void onData(SocketIOClient client, ResultBody data, AckRequest ackRequest) {
                log.info("浏览器发送消息："+data);
                if(null==data)
                    log.info("客户端发送错误消息");
            }
        });

        msg_namespace.addConnectListener(client -> {
            String uuid = client.getSessionId().toString();
            //存储SocketIOClient，用于发送消息
            if (MySocket.socketIOClientMap.containsKey(uuid)) {
                log.info("同一客户端连接存储最新连接:");
                MySocket.socketIOClientMap.replace(uuid, MySocket.socketIOClientMap.get(uuid), client);
            } else {
                MySocket.socketIOClientMap.put(uuid, client);
            }
            //回发消息
            log.info("客户端:" + uuid + "已连接");
            SocketIOResultBody socketIOResultBody = new SocketIOResultBody("200","connect","客户端:" + uuid + ","+String.valueOf(client.getRemoteAddress())+"已连接",null);
            sendMsgToClient(socketIOResultBody);
        });

        msg_namespace.addDisconnectListener(client -> {
            String uuid = client.getSessionId().toString();
            if (MySocket.socketIOClientMap.containsKey(uuid)) {
                SocketIOResultBody socketIOResultBody = new SocketIOResultBody("200","disconnect","客户端:" + uuid + ","+String.valueOf(client.getRemoteAddress())+"断开连接",null);
                sendMsgToClient(socketIOResultBody);
                MySocket.socketIOClientMap.remove(uuid);
                log.info("客户端:" + uuid + "断开连接");
            }
        });
        server.start();
    }

    /**
     * 发送消息给客户端
     * @param resultBody
     */
    public static void sendMsgToClient(SocketIOResultBody resultBody){
        for(SocketIOClient client : MySocket.socketIOClientMap.values()){
            if(client.isChannelOpen()){
                client.sendEvent(resultBody.getEventName(),resultBody);
            }
        }
    }


    /**
     * 此方法为获取client连接中的参数，可根据需求更改
     * @param client
     * @return
     */
    private String getParamsByClient(SocketIOClient client) {
        // 从请求的连接中拿出参数
        Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
        List<String> list = params.get("UID");
        if (list != null && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
}
